﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Dycox.Workflows
{
    public class WorkflowExecutionEventArgs : EventArgs
    {
        internal WorkflowExecutionEventArgs()
            : this(WorkflowExecutionContext.Current)
        {
        }

        protected WorkflowExecutionEventArgs(WorkflowExecutionContext context)
        {
            _context = context;
            if (_context == null)
                throw new WorkflowException(SR.GetString("no_context_found"));
        }

        private readonly WorkflowExecutionContext _context;

        public WorkflowExecutionContext Context
        {
            get { return _context; }
        }

    }

    public class StageCompletedEventArgs : WorkflowExecutionEventArgs
    {
        internal StageCompletedEventArgs(Manipulation.MoveResult mfr)
            : base()
        {
            _moveResult = mfr;
        }

        Manipulation.MoveResult _moveResult;

        public WFStep[] UpcomingSteps
        {
            get { return _moveResult.NewSteps; }
        }

        public Stage[] ImmediateStages
        {
            get { return _moveResult.ImmediateStages; }
        }

        public WFThread[] NewThreads
        {
            get
            {
                WorkflowForwardingContext ctx = this.Context;

                WFThread t0 = ctx.Thread;
                List<WFThread> list = new List<WFThread>(5);

                if (ctx.IsNewThread)
                    list.Add(t0);

                foreach (var step in _moveResult.NewSteps)
                {
                    WFThread t1 = step.Thread;

                    if (t0 != t1 && !list.Contains(t1))
                        list.Add(t1);
                }

                return list.ToArray();
            }
        }

        public new WorkflowForwardingContext Context
        {
            get { return (WorkflowForwardingContext)base.Context; }
        }

    }

    public delegate void StageCompletedEventHandler(object sender, StageCompletedEventArgs e);

    public class ProcessCompletedEventArgs : WorkflowExecutionEventArgs
    {
        public ProcessCompletedEventArgs()
            : base()
        {

        }

        private List<OperationArguments> _upcomingProcessCreationArguments;

        internal List<OperationArguments> UpcomingProcessCreationArguments
        {
            get
            {
                return _upcomingProcessCreationArguments;
            }
        }

        public void AddUpcomingProcessCreationArgument(string workflowName, StageOperationContract contract)
        {
            OperationArguments args = new OperationArguments(contract, Context.Arguments.DataSource);
            args.FrameType = FrameType.Bridging;
            args.WorkflowName = workflowName;

            if (_upcomingProcessCreationArguments == null)
                _upcomingProcessCreationArguments = new List<OperationArguments>(5);

            _upcomingProcessCreationArguments.Add(args);
        }

        internal bool HasUpcomingProcesses
        {
            get
            {
                return _upcomingProcessCreationArguments != null && _upcomingProcessCreationArguments.Count > 0;
            }
        }
    }

    public delegate void ProcessCompletedEventHandler(object sender, ProcessCompletedEventArgs e);

    public class ProcessAbortedEventArgs : WorkflowExecutionEventArgs
    {
        internal ProcessAbortedEventArgs(AbortProcessContext context)
            : base(context)
        {

        }

        public string Reason
        {
            get
            {
                return ((AbortProcessContext)Context).Reason;
            }
        }

        public WFProcess Process
        {
            get
            {
                return Context.Process;
            }
        }
    }

    public delegate void ProcessAbortedEventHandler(object sender, ProcessAbortedEventArgs e);
}
